package com.xunlai.infra.permission.business.service.impl;

import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qiniu.http.Response;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import com.xunlai.infra.permission.business.config.QiniuAuthKey;
import com.xunlai.infra.permission.business.converter.PhotoGalleryConverter;
import com.xunlai.infra.permission.business.dao.entity.PhotoGallery;
import com.xunlai.infra.permission.business.dao.entity.ScenicArea;
import com.xunlai.infra.permission.business.dao.entity.vo.PhotoGalleryAreaVo;
import com.xunlai.infra.permission.business.dao.repository.PhotoGalleryRepository;
import com.xunlai.infra.permission.business.dao.repository.ScenicAreaRepository;
import com.xunlai.infra.permission.business.dao.repository.vo.PhotoGalleryAreaVoRepository;
import com.xunlai.infra.permission.business.service.PhotoGalleryService;
import com.xunlai.infra.permission.business.vo.photoGallery.PhotoBatchCreateVo;
import com.xunlai.infra.permission.business.vo.photoGallery.PhotoCreateVo;
import com.xunlai.infra.permission.business.vo.photoGallery.PhotoListVo;
import com.xunlai.infra.permission.business.vo.photoGallery.QrCodeGenerateVo;
import com.xunlai.infra.permission.common.vo.BasePageRespVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.awt.*;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

/**
 * @author liang
 * @date 8/7/23 7:38 PM
 */
@Service
public class PhotoGalleryServiceImpl implements PhotoGalleryService {

    private UploadManager uploadManager;

    private QiniuAuthKey qiniuAuthKey;

    private PhotoGalleryRepository photoGalleryRepository;

    private PhotoGalleryAreaVoRepository photoGalleryAreaVoRepository;

    private ScenicAreaRepository scenicAreaRepository;

    @Override
    public String uploadPhoto(MultipartFile file) {
        Auth auth = Auth.create(qiniuAuthKey.accessKey(),qiniuAuthKey.secretKey());
        String uploadToken = auth.uploadToken(qiniuAuthKey.buket());
        try {
            Response response = uploadManager.put(file.getBytes(), null, uploadToken);
            ObjectMapper objectMapper = new ObjectMapper();
            DefaultPutRet defaultPutRet = objectMapper.readValue(response.bodyString(), DefaultPutRet.class);
            return qiniuAuthKey.domain() +"/"+defaultPutRet.key;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<String> batchUploadPhoto(MultipartFile[] file) {
        if(file == null || file.length == 0){
            return new ArrayList<>(0);
        }
        return Arrays.stream(file).map(this::uploadPhoto).collect(Collectors.toList());
    }

    @Override
    public Long createPhoto(PhotoCreateVo photoCreateVo) {
        PhotoGallery photoGallery = PhotoGalleryConverter.INSTANCE.convertCreateVo2Entity(photoCreateVo);
        Optional<ScenicArea> scenicAreaOptional = scenicAreaRepository.findById(photoCreateVo.getPhotoArea());
        scenicAreaOptional.ifPresent(scenicArea -> {
            if(StringUtils.isBlank(photoGallery.getScenicName())){
                //没有自定义景区名
                photoGallery.setScenicName(scenicArea.getScenicName());
            }
            photoGallery.setScenicProvince(scenicArea.getScenicProvince());
            photoGallery.setScenicCity(scenicArea.getScenicCity());
        });

        PhotoGallery save = photoGalleryRepository.save(photoGallery);
        return save.getId();
    }

    @Override
    public List<Long> batchCreatePhoto(PhotoBatchCreateVo photoBatchCreateVo) {
        String[] photoUris = photoBatchCreateVo.getPhotoUris();
        if(photoUris == null || photoUris.length == 0){
            return new ArrayList<>(0);
        }
        Optional<ScenicArea> scenicAreaOptional = scenicAreaRepository.findById(photoBatchCreateVo.getPhotoArea());
        List<PhotoGallery> galleryList = Arrays.stream(photoUris).map(s -> {
            PhotoGallery photoGallery = PhotoGalleryConverter.INSTANCE.convertCreateVo2Entity(photoBatchCreateVo);
            photoGallery.setPhotoUri(s);
            scenicAreaOptional.ifPresent(scenicArea -> {
                if(StringUtils.isBlank(photoGallery.getScenicName())){
                    //没有自定义景区名
                    photoGallery.setScenicName(scenicArea.getScenicName());
                }
                photoGallery.setScenicName(scenicArea.getScenicName());
                photoGallery.setScenicProvince(scenicArea.getScenicProvince());
                photoGallery.setScenicCity(scenicArea.getScenicCity());
            });
            return photoGallery;
        }).toList();
        Iterable<PhotoGallery> photoGalleries = photoGalleryRepository.saveAll(galleryList);
        return StreamSupport.stream(photoGalleries.spliterator(),false).map(PhotoGallery::getId).toList();
    }

    @Override
    public void updatePhoto(Long id, PhotoCreateVo photoCreateVo) {
        Optional<PhotoGallery> photoGalleryOptional = photoGalleryRepository.findById(id);
        if(photoGalleryOptional.isEmpty()) {
            return;
        }
        PhotoGallery photoGallery = photoGalleryOptional.get();
        Optional<ScenicArea> scenicAreaOptional = scenicAreaRepository.findById(photoCreateVo.getPhotoArea());
        scenicAreaOptional.ifPresent(scenicArea -> {
            photoGallery.setScenicName(scenicArea.getScenicName());
            photoGallery.setScenicProvince(scenicArea.getScenicProvince());
            photoGallery.setScenicCity(scenicArea.getScenicCity());
        });
        photoGallery.setPhotoArea(photoCreateVo.getPhotoArea());
        photoGallery.setPhotoUri(photoCreateVo.getPhotoUri());
        photoGallery.setPhotoDesc(photoCreateVo.getPhotoDesc());
        photoGalleryRepository.save(photoGallery);
    }

    @Override
    public BasePageRespVo<PhotoListVo> listPhoto(String photoType, String name, String userId, Integer pageNum, Integer pageSize,Boolean official) {
        PhotoGallery photoGallery = new PhotoGallery();
        if(Boolean.TRUE.equals(official)){
            photoGallery.setOfficial(true);
        }else {
            photoGallery.setCreateUser(Long.parseLong(userId));
        }
        photoGallery.setPhotoType(photoType);
        photoGallery.setPhotoName(name);
        pageNum = (pageNum == null || pageNum < 1) ? 1 : pageNum;
        int size = (pageSize == null || pageSize <= 0) ? 10 : pageSize;
        Page<PhotoGallery> photoGalleryPage = photoGalleryRepository.findAll(Example.of(photoGallery,
                        ExampleMatcher.matching()
                                .withIgnoreNullValues()
                                .withMatcher("photoName", g -> g.caseSensitive().contains())),
                PageRequest.of(pageNum - 1, size)
        );
        List<PhotoListVo> photoListVoList = photoGalleryPage.getContent().stream().map(PhotoGalleryConverter.INSTANCE::convertEntity2ListVo).toList();
        return new BasePageRespVo<>(photoListVoList,pageNum,size,photoGalleryPage.getTotalElements(), photoGalleryPage.getTotalPages());
    }

    @Override
    public BasePageRespVo<PhotoListVo> listPhoto(String province,String scenic,String photoType, String name, String userId, Integer pageNum, Integer pageSize,Boolean official) {
        PhotoGallery photoGallery = new PhotoGallery();
        if(Boolean.TRUE.equals(official)){
            photoGallery.setOfficial(true);
        }else {
            photoGallery.setCreateUser(Long.parseLong(userId));
        }
        if(StringUtils.isNotBlank(photoType)){
            photoGallery.setPhotoType(photoType);
        }
        if(StringUtils.isNotBlank(name)){
            photoGallery.setPhotoName(name);
        }
        if(StringUtils.isNotBlank(province)){
            photoGallery.setScenicProvince(province);
        }
        if(StringUtils.isNotBlank(scenic)){
            photoGallery.setScenicName(scenic);
        }
        pageNum = (pageNum == null || pageNum < 1) ? 1 : pageNum;
        int size = (pageSize == null || pageSize <= 0) ? 10 : pageSize;
        Page<PhotoGallery> photoGalleryPage = photoGalleryRepository.findAll(Example.of(photoGallery,
                        ExampleMatcher.matching()
                                .withIgnoreNullValues()
                                .withMatcher("photoName", g -> g.caseSensitive().contains())
                                .withMatcher("scenicName", g->g.caseSensitive().contains())
                                .withMatcher("scenicProvince", g->g.caseSensitive().contains())
                ),
                PageRequest.of(pageNum - 1, size, Sort.by(Sort.Direction.DESC,"createTime"))
        );
        List<PhotoListVo> photoListVoList = photoGalleryPage.getContent().stream().map(PhotoGalleryConverter.INSTANCE::convertEntity2ListVo).toList();
        return new BasePageRespVo<>(photoListVoList,pageNum,size,photoGalleryPage.getTotalElements(), photoGalleryPage.getTotalPages());
    }

    @Override
    public void createQrCodeToStream(QrCodeGenerateVo generateVo, OutputStream outputStream) {
        QrConfig qrConfig = new QrConfig(generateVo.getWidth(),generateVo.getHeight());
        qrConfig.setMargin(2);
        qrConfig.setForeColor(Color.BLACK);
        qrConfig.setBackColor(Color.WHITE);
        QrCodeUtil.generate(generateVo.getContent(),qrConfig,"png",outputStream);
    }

    @Override
    public void deletePhoto(Long id) {
        photoGalleryRepository.deleteById(id);
    }

    @Override
    public void deletePhoto(Long userId, Long id) {
        photoGalleryRepository.deleteByCreateUserAndId(userId,id);
    }

    @Autowired
    public void setUploadManager(UploadManager uploadManager) {
        this.uploadManager = uploadManager;
    }

    @Autowired
    public void setQiniuAuthKey(QiniuAuthKey qiniuAuthKey) {
        this.qiniuAuthKey = qiniuAuthKey;
    }

    @Autowired
    public void setPhotoGalleryRepository(PhotoGalleryRepository photoGalleryRepository) {
        this.photoGalleryRepository = photoGalleryRepository;
    }

    @Autowired
    public void setPhotoGalleryAreaVoRepository(PhotoGalleryAreaVoRepository photoGalleryAreaVoRepository) {
        this.photoGalleryAreaVoRepository = photoGalleryAreaVoRepository;
    }

    @Autowired
    public void setScenicAreaRepository(ScenicAreaRepository scenicAreaRepository) {
        this.scenicAreaRepository = scenicAreaRepository;
    }
}
